import json
import time
import random
import pickle
import datetime
import _thread
from weibosender.weibo.weibo import Weibo
from weibosender.dal.senders_dal import SendersDAL
from weibosender.dal.sent_msg_log_dal import SentMsgLogDAL
from weibosender.dal.sender_limit_log_dal import SenderLimitLogDAL


class WeiboSendMsgHandler:
    def __init__(self, senders, receivers, content):
        self.receivers = receivers
        self.receivers_count = len(self.receivers)

        self.content = content

        self.senders = senders
        self.senders_stack = []
        # self._init_senders()

    def _init_senders(self):
        for item in self.senders:
            sender_uid = item[3]
            sender_cookies_bytes = item[4]
            if not sender_uid or not sender_cookies_bytes:
                continue
            sender = {
                'id': item[0],
                'user_name': item[1],
                'uid': sender_uid,
                'cookies': pickle.loads(sender_cookies_bytes),
                'st': ''
            }
            self.senders_stack.append(sender)

    def send(self):
        # self._handle(self.get_sender())
        for i in range(len(self.senders)):
            item = self.senders[i]
            sender_uid = item[3]
            sender_cookies_bytes = item[4]
            if not sender_uid or not sender_cookies_bytes:
                continue
            sender = {
                'id': item[0],
                'user_name': item[1],
                'uid': sender_uid,
                'cookies': pickle.loads(sender_cookies_bytes),
                'st': ''
            }
            start_index = i * 100
            end_index = start_index + 100
            if start_index >= self.receivers_count:
                break
            if self.receivers_count < end_index:
                end_index = self.receivers_count
            receivers = self.receivers[start_index: end_index]
            _thread.start_new_thread(self.__send, (sender, receivers, random.randint(1, 10)))

        # print('Overall > done []~(￣▽￣)~*')

    def __send(self, sender, receivers, delay):
        print('%s > 将在%s秒后启动发送私信' % (sender['user_name'], delay))
        time.sleep(delay)
        self._handle(sender, receivers)

    def get_sender(self):
        sender = None
        if self.senders_stack and len(self.senders_stack) > 0:
            sender = self.senders_stack.pop()
        return sender

    def _handle(self, sender, receivers, index=0):
        if not sender:
            return False
        # 发送者信息
        sender_name = sender['user_name']
        sender_uid = sender['uid']

        # 接收者信息
        receiver = receivers[index]
        receiver_uid = receiver[0]
        receiver_name = receiver[1]
        msg = {
            'receiver_uid': receiver_uid,
            'content': self.content
        }
        result_send = Weibo.send_msg(sender, msg, WeiboSendMsgHandler._callback_st)
        if not result_send:
            print('私信发送失败 > 请求异常，Response is None，%s to %s' % (sender_name, receiver_name))
            return False

        response_text = result_send['response_text']
        if not response_text:
            WeiboSendMsgHandler._delay_send(index, '私信发送失败', '请求异常，Response text is None', sender_name, receiver_name)
            return self._handle(sender, receivers, index)

        if '帐号异常' in response_text:
            print('私信发送失败 > 帐号异常，%s，%s to %s' % (response_text, sender_name, receiver_name))
            return False

        try:
            obj_json = json.loads(response_text)
        except Exception as e:
            WeiboSendMsgHandler._delay_send(index, '私信发送失败', '%s\nException：%s' % (response_text, e), sender_name, receiver_name)
            return self._handle(sender, receivers, index)

        ok = obj_json['ok']
        msg = obj_json['msg']
        detail = None
        if ok == 1:
            # 记录日志
            SentMsgLogDAL.write_log((sender_uid, receiver_uid, self.content))
        else:
            if not msg:
                print('私信发送失败 > %s' % response_text)
                return False
            elif 'blocked' in msg:  # 黑名单
                SentMsgLogDAL.write_log((sender_uid, receiver_uid, msg), (0,))
            elif 'out of limit' in msg:  # 已达到今日最大发送数量
                SenderLimitLogDAL.write_log((sender_uid, msg))
                print('私信发送失败 > 该用户今日已达到最大发送数量')
                return False
            else:
                SentMsgLogDAL.write_log((sender_uid, receiver_uid, msg), (0,))

        index += 1
        WeiboSendMsgHandler._delay_send(index, msg, detail, sender_name, receiver_name)
        if index < len(receivers):
            return self._handle(sender, receivers, index)

        return True

    @staticmethod
    def _delay_send(index, msg, detail, sender_name, receiver_name):
        delay = random.randint(60, 120)
        detail = detail and detail or ''
        print('%s %s > %s%s to %s，将在%s秒后发送给下一个用户' % (index, msg, detail, sender_name, receiver_name, delay))
        # 1-3分钟后发给下一个用户
        time.sleep(delay)

    @staticmethod
    def _callback_st(sender):
        if sender['st']:
            SendersDAL.update_st((sender['st'], datetime.datetime.now(), sender['id']))
